package com.jichaoyun.sys.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jichaoyun.common.enums.MyExceptiontType;
import com.jichaoyun.common.ex.MyException;
import com.jichaoyun.common.utils.ExcelStyleUtils;
import com.jichaoyun.model.entity.Priceset;
import com.jichaoyun.model.entity.StationInfo;

import com.jichaoyun.common.model.PagedResult;

import com.jichaoyun.model.entity.Realdata;


import com.jichaoyun.model.vo.PriceSelectVo;
import com.jichaoyun.model.vo.PricesetVo;
import com.jichaoyun.sys.mapper.FlowHourMapper;
import com.jichaoyun.sys.mapper.PriceSetMapper;
import com.jichaoyun.sys.mapper.RealdataMapper;
import com.jichaoyun.sys.mapper.StationInfoMapper;
import com.jichaoyun.sys.service.PriceSetService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author zhen
 */
@Service
public class PriceSetServiceImpl extends ServiceImpl<PriceSetMapper, Priceset> implements PriceSetService {

    @Autowired
    private PriceSetMapper priceSetMapper;

    @Autowired
    private StationInfoMapper stationInfoMapper;

    @Resource
    private FlowHourMapper flowHourMapper;

    @Resource
    private RealdataMapper realdataMapper;

    @Resource
    private StationInfoServiceImpl stationInfoService;

    /**
     * 分页查找全部的 计费设置记录
     * @param pageNo
     * @return
     */
    @Override
    public PagedResult pageSelectRecords(Integer pageNo) {
        IPage<Priceset> page = new Page<>(pageNo, 10);
        LambdaQueryWrapper<Priceset> wp = new LambdaQueryWrapper<>();
        wp.orderByDesc(Priceset::getStartTime);
        IPage<Priceset> page1 = priceSetMapper.selectPage(page, wp);
        PagedResult pagedResult = new PagedResult();
        pagedResult.setRows(page1.getRecords());
        pagedResult.setPages(page1.getPages());
        pagedResult.setTotal(page1.getTotal());
        return pagedResult;
    }

    /**
     * 设置某个站点的费用开始启用
     * @param pricesetVo
     */
    @Override
    public void PriceSetOne(PricesetVo pricesetVo) {
        Priceset priceset = new Priceset();
        BeanUtils.copyProperties(pricesetVo,priceset);
        priceset.setInsertTime(LocalDateTime.now());
        priceset.setIsStart(false);

        LocalDateTime setTime = LocalDateTime.now().plusHours(1).withMinute(0).withSecond(0).withNano(0);
        priceset.setStartTime(setTime);
        priceSetMapper.insert(priceset);
    }

    @Override
    public void PriceSetBatch(List<PricesetVo> pricesetVos) {
        for (PricesetVo pricesetVo : pricesetVos) {
            Priceset priceset = new Priceset();
            BeanUtils.copyProperties(pricesetVo,priceset);
            priceset.setInsertTime(LocalDateTime.now());
            priceset.setIsStart(false);
            LocalDateTime setTime = LocalDateTime.now().plusHours(1).withMinute(0).withSecond(0).withNano(0);
            priceset.setStartTime(setTime);
            priceSetMapper.insert(priceset);
        }

    }

    @Override
    public PagedResult PricePageReg(Integer pageNo) {
        //分页查询
        IPage<StationInfo> page = new Page<>(pageNo, 10);
        LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
        wp.orderByAsc(StationInfo::getStationNo);
        IPage<StationInfo> page1 = stationInfoMapper.selectPage(page, wp);
        PagedResult pagedResult = new PagedResult();
        List<StationInfo> records = page1.getRecords();
        ArrayList<PricesetVo> pricesetVos = new ArrayList<>();
        //这里对上下限进行回显
        for (StationInfo record : records) {
            PricesetVo pricesetVo = new PricesetVo();
            pricesetVo.setPrice(record.getPriceHour());
            pricesetVo.setCoupon(record.getCoupon());
            pricesetVo.setXishu(record.getXishu());
            pricesetVo.setPipelossRate(record.getXishu());
            pricesetVo.setStationNo(record.getStationNo());
            pricesetVo.setStationName(record.getStationName());
            pricesetVos.add(pricesetVo);
        }
        pagedResult.setRows(pricesetVos);
        pagedResult.setPages(page1.getPages());
        pagedResult.setTotal(page1.getTotal());
        return pagedResult;

    }

    /**
     * 计费查询--分页
     *
     * @param pageNo
     * @param start
     * @param end
     * @return
     */
    @Override
    public PagedResult getPeriodSettleFeePage(Integer pageNo, LocalDateTime start, LocalDateTime end) {
        //先查出分页的基本信息
        start = start.withNano(0);
        end = end.withNano(0);

        Page<StationInfo> stationInfoPage = new Page<>(pageNo, 10);
        LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
        wp.orderByAsc(StationInfo::getStationNo);
        IPage<StationInfo> page1 = stationInfoMapper.selectPage(stationInfoPage, wp);
        PagedResult pagedResult = new PagedResult();
        pagedResult.setTotal(page1.getTotal());
        pagedResult.setPages(page1.getPages());

        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String settleStart = start.format(formatter);


        //组合成要返回的结果
        ArrayList<PriceSelectVo> priceSelectVos = new ArrayList<>();
        List<StationInfo> records = page1.getRecords();
        for (StationInfo record : records) {
            PriceSelectVo priceSelectVo = new PriceSelectVo();
            priceSelectVo.setStationNo(record.getStationNo());
            priceSelectVo.setStationName(record.getStationName());
            priceSelectVo.setPipeLossRate(record.getPipelossRate());
            priceSelectVo.setSettlePeriod(start.format(formatter)+"-"+end.format(formatter));
            Integer stationNo = record.getStationNo();
            Float orginalFlow =0f;
            Float amendFlow =0f;
            Float feeFlow =0f;
            Float amendGap = 0f;

            while (start.compareTo(end)<0){
                List<Realdata> realdataList1 = realdataMapper.historySelect(stationNo, start, start.plusMinutes(3));
                Realdata realdata1 = realdataList1.get(0);
                start = start.plusHours(1);
                if(start.compareTo(end)>0){
                    break;
                }
                List<Realdata> realdataList2 = realdataMapper.historySelect(stationNo, start, start.plusMinutes(3));
                Realdata realdata2 = realdataList2.get(0);

                if(realdata2==null || realdata1==null){
                    throw new MyException(MyExceptiontType.DATAERROR2,null);
                }

                //计算这个小时内用了多少的流量
                float spend =   realdata2.getTotal()- realdata1.getTotal();
                orginalFlow+=spend;

                //计算修正后的流量
                float amend_spend= spend - realdata1.getDownFlow() >0 ? spend : realdata1.getDownFlow();
                amendFlow+=amend_spend;

                //修正后的差额
                amendGap+=(amend_spend-spend);

                //计算这个小时的花费
                float fee = 0f;
                float priceHour = realdata1.getHourPrice().floatValue() - realdata1.getCoupon().floatValue();
                if(spend - realdata1.getUpFlow() >0){
                    fee+=realdata1.getUpFlow() * priceHour ;
                    fee+=(spend - realdata1.getUpFlow())*(1+realdata1.getXishu())*priceHour;
                }else{
                    fee+=spend*priceHour;
                }
                fee *=(1+realdata1.getFixpipelossRate());
                feeFlow+=fee;
            }
            priceSelectVo.setOriginality(orginalFlow);
            priceSelectVo.setAmend(amendFlow);
            priceSelectVo.setFee(new BigDecimal(feeFlow));
            priceSelectVo.setAmendGap(amendGap);
            //判断结算结束的时间
            if(start.compareTo(end)!=0){
                start = start.minusHours(1);
            }
            priceSelectVo.setSettlePeriod(settleStart+'~'+start.format(formatter));
            priceSelectVo.setSelectPeriod(settleStart+'~'+end.format(formatter));
            priceSelectVos.add(priceSelectVo);
        }
        pagedResult.setRows(priceSelectVos);
        return pagedResult;
    }

    /**
     * 计费查询--单用户分页
     *
     * @param stationNo
     * @param pageNo
     * @param start
     * @param end
     * @return
     */
    @Override
    public PagedResult getPeriodSettleFeePage(Integer stationNo, Integer pageNo, LocalDateTime start, LocalDateTime end) {
        //先查出分页的基本信息
        start = start.withNano(0);
        end = end.withNano(0);

        //计算出一共要多少条结果
        int recordsTotal = 0;
        LocalDateTime start1 = start;
        LocalDateTime end1 =end;
        while (end.minusHours(1).compareTo(start1)>=0){
            recordsTotal++;
            start1 = start1.plusHours(1);
        }

        StationInfo stationInfo= stationInfoMapper.selectById(stationNo);
        PagedResult pagedResult = new PagedResult();
        pagedResult.setTotal(recordsTotal);
        pagedResult.setPages(recordsTotal/10+1);

        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String settleStart = start.format(formatter);

        //组合成要返回的结果
        ArrayList<PriceSelectVo> priceSelectVos = new ArrayList<>();

        //初始化当前页的查询开始时间
        for(int i =0;i<(pageNo-1)*10;i++){
            start.plusHours(i);
        }
        start.plusHours(1);

        for (int i= 0;i<10;i++) {
            start = start.plusHours(i);
            end = start.plusHours(1);
            if(end.compareTo(end1)>0){
                break;
            }
            PriceSelectVo priceSelectVo = new PriceSelectVo();
            priceSelectVo.setStationNo(stationInfo.getStationNo());
            priceSelectVo.setStationName(stationInfo.getStationName());
            priceSelectVo.setPipeLossRate(stationInfo.getPipelossRate());
            priceSelectVo.setSettlePeriod(start.format(formatter)+"~"+end.format(formatter));

            List<Realdata> realdataList1 = realdataMapper.historySelect(stationNo, start, start.plusMinutes(3));
            Realdata realdata1 = realdataList1.get(0);

            List<Realdata> realdataList2 = realdataMapper.historySelect(stationNo, end, end.plusMinutes(3));
            Realdata realdata2 = realdataList2.get(0);

            if(realdata2==null || realdata1==null){
                throw new MyException(MyExceptiontType.DATAERROR2,null);
            }

            //计算这个小时内用了多少的流量
            float spend =  realdata2.getTotal()- realdata1.getTotal();

            //计算修正后的流量
            float amend_spend= spend - realdata1.getDownFlow() >0 ? spend : realdata1.getDownFlow();

            //修正后的差额
            float amendGap =(amend_spend-spend);

            //计算这个小时的花费
            float fee = 0f;

            //优惠后的单价
            float hourPrice = realdata1.getHourPrice().floatValue()-realdata1.getCoupon().floatValue();
            if(spend - realdata1.getUpFlow() >0){
                fee+=realdata1.getUpFlow() * hourPrice;
                fee+=(spend - realdata1.getUpFlow())*(1+realdata1.getXishu())*hourPrice;
            }else{
                fee+=spend* hourPrice;
            }
            fee = fee*(1+realdata1.getFixpipelossRate());

            priceSelectVo.setOriginality(spend);
            priceSelectVo.setAmend(amendGap);
            priceSelectVo.setFee(new BigDecimal(fee));
            priceSelectVo.setAmendGap(amendGap);
            //判断结算结束的时间
            if(start.compareTo(end)!=0){
                start = start.minusHours(1);
            }
            if(end.plusHours(1).compareTo(end1)>0){
                priceSelectVo.setSelectPeriod(start.format(formatter)+'~'+end1.format(formatter));
            }else{
                priceSelectVo.setSelectPeriod(start.format(formatter)+'~'+end.format(formatter));
            }
            priceSelectVos.add(priceSelectVo);
        }
        pagedResult.setRows(priceSelectVos);
        return pagedResult;
    }

    /**
     * 计费查询--单用户分页导出到excel
     *
     * @param start
     * @param end
     * @param response
     * @return
     */
    @Override
    public void getPeriodSettleFeePage(LocalDateTime start, LocalDateTime end, HttpServletResponse response) throws IOException {
        //先查出分页的基本信息
        start = start.withNano(0);
        end = end.withNano(0);

        List<StationInfo> records = stationInfoService.getAllUsedStation();

        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String settleStart = start.format(formatter);

        //组合成要返回的结果
        ArrayList<PriceSelectVo> priceSelectVos = new ArrayList<>();
        for (StationInfo record : records) {
            PriceSelectVo priceSelectVo = new PriceSelectVo();
            priceSelectVo.setStationNo(record.getStationNo());
            priceSelectVo.setStationName(record.getStationName());
            priceSelectVo.setPipeLossRate(record.getPipelossRate());
            priceSelectVo.setSettlePeriod(start.format(formatter)+"-"+end.format(formatter));
            Integer stationNo = record.getStationNo();
            Float orginalFlow =0f;
            Float amendFlow =0f;
            Float feeFlow =0f;
            Float amendGap = 0f;

            while (start.compareTo(end)<0){
                List<Realdata> realdataList1 = realdataMapper.historySelect(stationNo, start, start.plusMinutes(3));
                Realdata realdata1 = realdataList1.get(0);
                start = start.plusHours(1);
                if(start.compareTo(end)>0){
                    break;
                }
                List<Realdata> realdataList2 = realdataMapper.historySelect(stationNo, start, start.plusMinutes(3));
                Realdata realdata2 = realdataList2.get(0);

                if(realdata2==null || realdata1==null){
                    throw new MyException(MyExceptiontType.DATAERROR2,null);
                }

                //计算这个小时内用了多少的流量
                float spend =   realdata2.getTotal()- realdata1.getTotal();
                orginalFlow+=spend;

                //计算修正后的流量
                float amend_spend= spend - realdata1.getDownFlow() >0 ? spend : realdata1.getDownFlow();
                amendFlow+=amend_spend;

                //修正后的差额
                amendGap+=(amend_spend-spend);

                //计算这个小时的花费
                float fee = 0f;
                float priceHour = realdata1.getHourPrice().floatValue() - realdata1.getCoupon().floatValue();
                if(spend - realdata1.getUpFlow() >0){
                    fee+=realdata1.getUpFlow() * priceHour ;
                    fee+=(spend - realdata1.getUpFlow())*(1+realdata1.getXishu())*priceHour;
                }else{
                    fee+=spend*priceHour;
                }
                fee *=(1+realdata1.getFixpipelossRate());
                feeFlow+=fee;
            }
            priceSelectVo.setOriginality(orginalFlow);
            priceSelectVo.setAmend(amendFlow);
            priceSelectVo.setFee(new BigDecimal(feeFlow));
            priceSelectVo.setAmendGap(amendGap);
            //判断结算结束的时间
            if(start.compareTo(end)!=0){
                start = start.minusHours(1);
            }
            priceSelectVo.setSettlePeriod(settleStart+'~'+start.format(formatter));
            priceSelectVo.setSelectPeriod(settleStart+'~'+end.format(formatter));
            priceSelectVos.add(priceSelectVo);
        }
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("计费查询导出表", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(ExcelStyleUtils.getHeadStyle(), ExcelStyleUtils.getContentStyle());

            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), PriceSelectVo.class)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .autoCloseStream(Boolean.FALSE)
                    .sheet("sheet1")
                    .doWrite(priceSelectVos);
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = MapUtils.newHashMap();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSONUtils.toJSONString(map));
        }




    }

    /**
     * 计费查询--单用户导出到excel
     *
     * @param stationNo
     * @param start
     * @param end
     * @param response
     * @return
     */
    @Override
    public void getPeriodSettleFeePage(Integer stationNo, LocalDateTime start, LocalDateTime end, HttpServletResponse response) throws IOException {
        //先查出分页的基本信息
        start = start.withNano(0);
        end = end.withNano(0);

        //计算出一共要多少条结果
        int recordsTotal = 0;
        LocalDateTime start1 = start;
        LocalDateTime end1 =end;
        while (end.minusHours(1).compareTo(start1)>=0){
            recordsTotal++;
            start1 = start1.plusHours(1);
        }
        StationInfo stationInfo= stationInfoMapper.selectById(stationNo);

        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String settleStart = start.format(formatter);

        //组合成要返回的结果
        ArrayList<PriceSelectVo> priceSelectVos = new ArrayList<>();


        for (int i= 0;i<recordsTotal;i++) {
            start = start.plusHours(i);
            end = start.plusHours(1);
            if(end.compareTo(end1)>0){
                break;
            }
            PriceSelectVo priceSelectVo = new PriceSelectVo();
            priceSelectVo.setStationNo(stationInfo.getStationNo());
            priceSelectVo.setStationName(stationInfo.getStationName());
            priceSelectVo.setPipeLossRate(stationInfo.getPipelossRate());
            priceSelectVo.setSettlePeriod(start.format(formatter)+"~"+end.format(formatter));

            List<Realdata> realdataList1 = realdataMapper.historySelect(stationNo, start, start.plusMinutes(3));
            Realdata realdata1 = realdataList1.get(0);

            List<Realdata> realdataList2 = realdataMapper.historySelect(stationNo, end, end.plusMinutes(3));
            Realdata realdata2 = realdataList2.get(0);

            if(realdata2==null || realdata1==null){
                throw new MyException(MyExceptiontType.DATAERROR2,null);
            }

            //计算这个小时内用了多少的流量
            float spend =  realdata2.getTotal()- realdata1.getTotal();

            //计算修正后的流量
            float amend_spend= spend - realdata1.getDownFlow() >0 ? spend : realdata1.getDownFlow();

            //修正后的差额
            float amendGap =(amend_spend-spend);

            //计算这个小时的花费
            float fee = 0f;

            //优惠后的单价
            float hourPrice = realdata1.getHourPrice().floatValue()-realdata1.getCoupon().floatValue();
            if(spend - realdata1.getUpFlow() >0){
                fee+=realdata1.getUpFlow() * hourPrice;
                fee+=(spend - realdata1.getUpFlow())*(1+realdata1.getXishu())*hourPrice;
            }else{
                fee+=spend* hourPrice;
            }
            fee = fee*(1+realdata1.getFixpipelossRate());

            priceSelectVo.setOriginality(spend);
            priceSelectVo.setAmend(amendGap);
            priceSelectVo.setFee(new BigDecimal(fee));
            priceSelectVo.setAmendGap(amendGap);
            //判断结算结束的时间
            if(start.compareTo(end)!=0){
                start = start.minusHours(1);
            }
            if(end.plusHours(1).compareTo(end1)>0){
                priceSelectVo.setSelectPeriod(start.format(formatter)+'~'+end1.format(formatter));
            }else{
                priceSelectVo.setSelectPeriod(start.format(formatter)+'~'+end.format(formatter));
            }
            priceSelectVos.add(priceSelectVo);
        }

        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode(stationInfo.getStationName().trim()+" 查询导出表", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(ExcelStyleUtils.getHeadStyle(), ExcelStyleUtils.getContentStyle());

            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), PriceSelectVo.class)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .autoCloseStream(Boolean.FALSE)
                    .sheet("sheet1")
                    .doWrite(priceSelectVos);
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = MapUtils.newHashMap();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSONUtils.toJSONString(map));
        }



    }


}
